home *** CD-ROM | disk | FTP | other *** search
- {*
- ** This program was sent to me (via John Stiwinter) from Jeff Harris.
- ** Thanks Jeff!
- **
- ** Note that if one were to rewrite the following - removing comments -
- ** using built-in ACE commands/functions, the whole thing would take about
- ** half a dozen lines of code. This should give you some idea of the work
- ** being done by ACE internally when you issue a command like WINDOW/SCREEN.
- *}
-
- REM A very simple "Hello World" Program That Runs Under ACE to demonstrate the
- REM use of system calls in ACE.
- REM Ported to AmigaBasic and ACE by Jeffrey Harris from Example in Intuition
- REM RKM. This program is public domain.
- REM Note: This Program uses BMAPS files for the AmigaDOS 1.3 Libraries!
- REM Compatibility with 2.0+ Libraries and BMAPS has not been tested and is
- REM not guaranteed, although the program runs fine on AmigaDOS 3.0.
- REM The program runs from a shell, or from WB, but diagnostics are only
- REM printed when run from a shell window.
- REM There are four ways of accessing structures for making system calls:
- REM The first is to do an include from a header file (#?.h), which has the
- REM structure predefined.
- REM Note: the '#' on the following line is a preprocessor directive. The
- REM '<' and '>' brackets around "intuition.h" tell the preprocessor to look
- REM in the aceinclude: directory.
- #include <intuition.h> 'include file for window and screen stuff
- REM The second way to access a structure is for a programmer to define it
- REM himself.
- REM Define the MsgPort structure we will need using a self-made STRUCT
- REM definition (this definition is actually a system structure that comes
- REM from the EXEC RKM).
- STRUCT MsgPort
- STRING mp_Node SIZE 14 'this is actually a Node structure
- BYTE mp_Flags
- BYTE mp_SigBit
- LONGINT mp_SigTask '* (a pointer) to a Task structure
- STRING mp_MsgList SIZE 14 'this is actually a message linked list
- END STRUCT 'structure
- REM To access system routines, we must first open the Libraries that contain
- REM them. The next four lines do that. These are the libraries we will need
- REM for this program.
- LIBRARY "diskfont.library"
- LIBRARY "exec.library"
- LIBRARY "intuition.library"
- LIBRARY "graphics.library"
- REM Next, we must tell ACE which system routines we want out of those
- REM libraries. It is more efficient during compiling to put those routines
- REM together that come from the same library.
- REM initialize function calls to intuition
- DECLARE FUNCTION OpenWindow&() LIBRARY
- DECLARE FUNCTION OpenScreen&() LIBRARY
- DECLARE FUNCTION CloseWindow() LIBRARY 'this function does not return a
- REM parameter, so the trailing '&' is not necessary.
- DECLARE FUNCTION CloseScreen() LIBRARY 'ditto
- REM initialize function calls to Exec
- DECLARE FUNCTION AllocMem&() LIBRARY
- DECLARE FUNCTION FreeMem() LIBRARY 'ditto
- REM since Wait() conflicts with an Amigabasic Reserved Work, the system call
- REM has been renamed xWait
- DECLARE FUNCTION xWait&() LIBRARY
- REM initialize function calls to DiskFont Library
- DECLARE FUNCTION OpenDiskFont&() LIBRARY
- DECLARE FUNCTION CloseFont() LIBRARY 'does not return a parameter
- REM initialize function calls to Graphics Library
- DECLARE FUNCTION Text&() LIBRARY
- DECLARE FUNCTION Move&() LIBRARY
- REM Let's play it safe, and initialize our pointers; always a good practice!
- MyMem&=0 'this will be the pointer to our allocated memory
- MyScreen&=0 'this will be the pointer to our defined screen structure
- rp&=0 'pointer to window's rastport (for text and graphics stuff)
- TF&=0 'pointer to our TextFont structure
- REM since the next two pointers directly access defined structures, we
- REM DECLARE them, as shown; the '*' in front of the pointer signifies that
- REM the system will allocate the memory for the structure and initialize it
- REM later.
- DECLARE STRUCT MsgPort *MyUP 'used to wait on a closewindow gadget click
- DECLARE STRUCT WindowStruct *MyWindow 'the pointer to our window structure
- REM a good programming practice is to provide a short main routine, and put
- REM the job of doing various things in subroutines or subprograms, which
- REM makes the program very structured, modular, and easy to follow.
- REM Labels always have a trailing colon; the 'Main:' is not needed, but
- REM provides clarity.
- Main:
- gosub GetMem 'the memory allocation subroutine
- REM Note how the IF-THEN statements keep the program in check; an error
- REM returned by one subroutine could cause a system crash in the next if we
- REM did not provide for it.
- IF MyMem&<>0 THEN GOSUB ScrnSetup 'the screen setup and display subroutine
- IF MyScreen&<>0 THEN GOSUB WinSetup 'the window setup and display subroutine
- IF MyWindow<>0 THEN GOSUB WaitSig 'subroutine to wait on a close-window
- REM gadget mouse click
- GOSUB CleanUp 'cleans up the program after an error or that mouse click
- END 'terminates the program; very important! Otherwise, the program runs
- REM right through the subroutines again, often with disasterous results!
- GetMem:
- REM 'Before' has to be a long integer because the value it returns could be
- REM larger than 65,000; hence the trailing '&'
- Before&=FRE(-1) 'check the total system free memory before we start
- REM allocating it; used for checking that all the memory we allocated is
- REM freed at the end of the program. Note that since the program has started,
- REM and the system has to allocate it some memory to load, the memory
- REM displayed by workbench may not be the same as displayed here.
- PRINT "Memory Before Allocations is ";Before&
- REM To allocate memory using AllocMem&(), we need to tell it what we need...
- MemFlags&=SHL(1,16)+2 'Clear Mem Block, CHIP Mem (for INTUITION AND GRAPHICS
- REM stuff) and how much. One hundred twenty bytes is sufficient for our
- REM needs here. Note 120 must be represented as a long integer: 120&.
- REM Now, make the system call to allocate the needed memory; note that instead,
- REM we could have used the equivalent ACE Command: MyMem&=Alloc(120,3)
- MyMem&=AllocMem&(120&,MemFlags&) 'Allocate 120 Bytes of Memory
- REM AllocMem&() returns the pointer to our memory, or zero if it could not
- REM allocate any memory.
- IF MyMem&=0 THEN
- PRINT "Insufficient Memory"
- ELSE
- PRINT "My memory is located at ";MyMem&
- REM now determine how much memory is free, and show; difference should equal
- REM what we asked for.
- After&=FRE(-1)
- PRINT "Memory After is Allocation is ";After&
- PRINT "Memory Has Been Reduced by ";After& - Before&
- END IF
- RETURN 'completed what we need to in this routine; go back to calling routine
- ScrnSetup:
- REM First thing we want to do (but optional) is to select the screen font;
- REM to do that, we set up TextAttr Structure using the third method of
- REM creating a structure: using an array, which we must DIMension before use
- DIM TextAttr&(1) 'use long words for array; it is important that we align the
- REM infomation properly; the '(1)' signifies that we need only two array
- REM elements.
- Myfont$="garnet.font" 'decide on a font; needs to be in fonts: directory
- REM The first variable in the structure is a pointer to the string with the
- REM font name; we pass that address using the SADD function for strings.
- TextAttr&(0)=SADD(Myfont$) 'pointer to our Font in TextAttr Structure
- REM the second variable are the flags that tell us about the font: point size
- REM is a word-sized variable, which resides in the upper word of the long word
- REM TextAttr&(1); got that? Next comes style attributes in the next byte, and
- REM finally any flags in the lowest byte of that long word. Graphically:
- REM bit: 0 (LSB) 7 15 23 31(MSB)
- REM point size style flags
- REM <------- increasing memory address
- TextAttr&(1)=SHL(9,16)+66 'flags for font - designed (not scalable),
- REM diskbased (that's the 66 part), normal attributes (for style = 0),
- REM 9 Point font.
- REM Note that it is not really necessary to actually open the font, as the
- REM screen statement sets the default font by using the TextAttr structure
- REM directly.
- REM However, with the OpenDiskFont call, we could have set up another
- REM TextAttr structure, called OpenDiskFont() and SetFont() and changed to a
- REM different font for our window text.
- TF&=OpenDiskFont&(@TextAttr&(0)) 'Open the normal attribute, 9 point Garnet Font
- IF TF&<>0 THEN
- PRINT "Address for TextFont is ";TF&
- ELSE
- PRINT "Requested Font Open Failed"
- REM will fail if font is not in Fonts: or Diskfont.library is not in
- REM libs:
- END IF
- REM Set Up Screen Structure
- REM The fourth way of setting up a structure in memory is to allocate some
- REM memory, as we have done, and poke the data into that allocated memory.
- REM WARNING! Make sure you know what you are doing! Poking into unallocated
- REM memory, or beyond what you have allocated, can cause a system crash, as
- REM can putting inappropriate values in memory for a particular structure
- REM element, or placing them inappropriately (ie, wrong memory location, or
- REM wrong offset within a word or longword).
- REM To set up a screen structure, poke the required information into the
- REM memory locations as shown. This information comes from the Intuition RKM;
- REM the 2.0 autodoc manual shows structure offsets, which makes doing this
- REM MUCH easier. Some values are byte or word length, and so must be shifted
- REM 8, 16, or 24 bits to put them in the right location. Memory mapping for
- REM byte and word values (16 bits) is the same as for arrays discussed above.
- REM What each value represents is shown in a comment after each line.
- POKEL MyMem&,SHL(20,16)+20 'left edge, top edge
- POKEL MyMem&+4,SHL(320,16)+200 'width, height
- POKEW MyMem&+8,4 'depth; note that poking a byte (POKE) or word (POKEW) can
- REM save having to make an offset, but takes more POKEs overall.
- POKEW MyMem&+10,SHL(21,8)+14 'Detail,block Pen (No View Modes Set)
- POKEW MyMem&+14,15 'Custom Screen
- POKEL MyMem&+16,@TextAttr&(0) 'Default Font; note how we pass the address of
- REM our TextAttr structure?
- Title$="A Simple Screen"
- POKEL MyMem&+20,SADD(Title$) 'Default Title for This Screen
- REM all the data for our screen is defined; now make the call to open it
- MyScreen&=OpenScreen&(MyMem&) 'open the screen
- IF MyScreen&=0 THEN 'MyScreen& will remain 0 if screen couldn't be opened
- PRINT "Open Screen Failed"
- ELSE 'otherwise we will see a screen pop open before our very eyes!
- PRINT "Screen Pointer is ";MyScreen& 'address to Screen structure
- END IF
- RETURN 'finished playing with the screen
- WinSetup:
- REM Time to set up a NewWindow Structure.
- REM In general, we follow the same procedure as setting up a new screen, but
- REM some of the parameters are different.
- POKEL MyMem&+60,SHL(20,16)+20 'left edge,top edge
- POKEL MyMem&+64,SHL(300,16)+100 'Width,height
- POKEW MyMem&+68,SHL(23,8)+5 'Detail,block Pen
- POKEL MyMem&+70,SHL(1,9) 'IDCMP Flags; in this case, notify us user clicks the
- REM CloseWindow gadget.
- POKEL MyMem&+74,SHL(1,12)+10 'Window Flags and Settings - Smart_Refresh,
- REM Activate Window, give us a Dragbar and CloseWindow Gadget, please!
- Title$="A Simple Window"
- POKEL MyMem&+86,SADD(Title$) 'Pointer to Window Title
- POKEL MyMem&+90,MyScreen& 'Pointer to screen for this window (this is only
- REM needed for a custom screen, as we are using in this example).
- POKEW MyMem&+106,15 'Value for a Screen Type that Corresponds to our screen -
- REM in this case, a custom screen (as opposed to the Workbench screen).
- REM Now, since we previously defined the Window Structure by #including
- REM intuition.h, and DECLARED MyWindow to be a pointer to a window structure,
- REM we can now link a specific address to that pointer by using it as the
- REM return value for our open window call; NOTE that the address passed to
- REM the OpenWindow call is the STARTING address of where we started POKING
- REM the NewWindow data into our allocated memory (this is true for any
- REM structure):
- MyWindow=OpenWindow&(MyMem&+60)
- IF MyWindow=0 THEN 'MyWindow will remain 0 if window couldn't be opened
- PRINT "Open Failed"
- ELSE 'otherwise, a new window will pop open on the screen before our eyes!
- PRINT "Window Pointer is ";MyWindow
- END IF
- REM Now PRINT Some Text to demonstrate what we can do.
- Tx1$="Hello World!" 'The text to print.
- REM since we have explicitly used a structure, we can access it's elements
- REM directly as follows; in this case, we want the address of the RastPort.
- rp&=MyWindow->RPort 'beats rp&=PEEKL(MyWindow+50&), doesn't it?
- CALL Move(rp&,100&,60&) 'Move the Cursor within the window to position 100
- REM pixels to the left of the current position, and 60 pixels down.
- ER1=Text&(rp&,SADD(Tx1$),LEN(Tx1$)) 'Put our text in the window
- RETURN 'finished with window and text stuff
- WaitSig: 'Here's we we sleep until the User clicks on the close gadget
- REM the next two lines can be translated as "wait until a special signal
- REM (mp_SigBit) arrives in the msgport (UserPort) of the window (MyWindow)"
- MyUP = MyWindow->UserPort 'need to access the address of our MsgPort for the
- REM window; note how again, we make use of an explicit structure.
- REM NOTE: In general, one would have to check not only the bit, but also the
- REM specific msg that arrived in the MsgPort, since ANY message will awaken
- REM our task. In this case, we have defined only one event (via the IDCMP
- REM flag in the NewWindow Structure above) which gets reported to our task,
- REM so we can be sure if we get a message, it's a closewindow click!
- Call xWait&(SHL(1,MyUP->mp_SigBit)) 'this actually puts our task to sleep
- PRINT "Sig Value = ";MyUP->mp_SigBit
- RETURN 'got the closewindow click; let's go back.
- CleanUp: 'Come Here on Error or after click on window gadget
- REM General Rules: Close any resources opened (libraries, fonts, devices);
- REM Close in reverse order of opening.
- REM Note that these MUST be done in the order listed.
- IF MyWindow<>0 THEN CALL CloseWindow(MyWindow) 'Close the window, if opened
- IF MyScreen&<>0 THEN CALL CloseScreen(MyScreen&) 'Close the screen, if opened
- IF MyMem&<>0 THEN
- IF TF&<>0 THEN CALL CloseFont(TF&) 'Close the font we opened
- CALL FreeMem(MyMem&,120&) 'Give our memory back to the system
- END IF
- LIBRARY CLOSE 'Close all the libraries
- After&=FRE(-1)
- PRINT "Memory After Cleaning Up is ";After&
- PRINT "Memory Has Been Reduced by ";After& - Before& 'just a check; should be
- REM 0.
- REM NOTE: May be non-zero if system opened fonts, or other tasks have
- REM allocated memory while program is running.
- RETURN 'finished here!
-